/***************************************************************************
 *  Filename: programmanager.cpp
 *  Class: ProgramManager
 *
 *  Copyright 2012  Xander van Kooten
 *  <xandervk@gmail.com>
 *
 *  Copyright 2012  Mario Henrique Voorsluys
 *  <forcaeluz@gmail.com>
 *
 ****************************************************************************/

/*
 *
 * This file is part of Parsax-Remote-Controller.
 *
 *    Parsax-Remote-Controller is free software: you can redistribute it
 *    and/or modify it under the terms of the GNU General Public License
 *    as published by the Free Software Foundation, either version 3 of the
 *    License, or (at your option) any later version.
 *
 *    Parsax-Remote-Controller is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with Parsax-Remote-Controller.
 *    If not, see <http://www.gnu.org/licenses/>.
 */

#include "programmanager.h"

ProgramManager::ProgramManager(QObject *parent) :
    QObject(parent)
{
    communicationHandler = new SlaveCommunicator(this);
    parser = new MessageParser(this);
    QSettings settings("CCC-Buienradar", "Parsax Slave");
    settings.beginGroup("network");
    QString listenAddress = settings.value("listenaddress", "0.0.0.0").toString();
    int portNumber = settings.value("listenport", 33300).toInt();
    communicationHandler->initialize(listenAddress, portNumber);
    settings.endGroup();
    connect(communicationHandler, SIGNAL(validDataReceived(QString)), parser, SLOT(handleMessage(QString)));
    connect(communicationHandler, SIGNAL(connectionEstablished()), SLOT(sendAllStatus()));
    connect(parser, SIGNAL(startProgramReceived(QString)), SLOT(startProgram(QString)));
    connect(parser, SIGNAL(startProgramReceived(QString,QString,QStringList)), SLOT(startProgram(QString,QString,QStringList)));
    connect(parser, SIGNAL(stopProgramReceived(QString)), SLOT(stopProgram(QString)));
    connect(parser, SIGNAL(cmdReceived(QString,QString)), SLOT(sendCmdToProgram(QString,QString)));

}


void ProgramManager::startProgram(QString id){
    if(processesManager.isEmpty()){
        qWarning() << "[ProgramManager] No processes are being managed yet";
        return;
    }
    if(!processesManager.contains(id)){
        qWarning() << "[ProgramManager] No process with id=" << id << "is managed";
        qWarning() << "[ProgramManager] Available programs" << processesManager.keys();
        return;
    }
    ProcessManager *prcsMngr = processesManager.value(id);

    connect(prcsMngr, SIGNAL(statusReceived(QString,QString)), SLOT(sendProgramStatus(QString,QString)), Qt::UniqueConnection);
    connect(prcsMngr, SIGNAL(cloReceived(QString,int,QString)), SLOT(sendProgramClo(QString,int,QString)), Qt::UniqueConnection);

    prcsMngr->start();
}

void ProgramManager::startProgram(QString id, QString program, QStringList params){
    if(processesManager.contains(id)){
        qWarning() << "[ProgramManager] Program with id " << id << "already exists";
        ProcessManager *tmpManager = processesManager.value(id);
        if(tmpManager->getStatus()=="notrunning"){
            tmpManager->setProgram(program);
            tmpManager->setParameters(params);
        }
        startProgram(id);
        return;
    }
    ProcessManager *prscMngr = new ProcessManager(id, this);
    prscMngr->setProgram(program);
    prscMngr->setParameters(params);
    processesManager.insert(id, prscMngr);
    startProgram(id);
}

void ProgramManager::stopProgram(QString id){
    if(processesManager.isEmpty()){
        qWarning() << "[ProgramManager] No processes are being managed yet";
        return;
    }
    if(!processesManager.contains(id)){
        qWarning() << "[ProgramManager] No process with id=" << id << "is managed";
        return;
    }
    ProcessManager *prcsMngr = processesManager.value(id);
    prcsMngr->stop();

}

void ProgramManager::restartProgram(QString id){
    if(processesManager.isEmpty()){
        qWarning() << "[ProgramManager] No processes are being managed yet";
        return;
    }
    if(processesManager.contains(id)){
        qWarning() << "[ProgramManager] No process with id=" << id << "is managed";
        return;
    }
    ProcessManager *prcsMngr = processesManager.value(id);
    prcsMngr->restart();
}

void ProgramManager::sendProgramStatus(QString id, QString status){
    QByteArray message = parser->statusMessage(id, status);
    communicationHandler->sendData(message);
}

void ProgramManager::sendProgramClo(QString id, int type, QString msg){
    QByteArray message = parser->cloMessage(id, type, msg);
    communicationHandler->sendData(message);
}

void ProgramManager::sendCmdToProgram(QString id, QString cmd){
    ProcessManager *prcsMngr = processesManager.value(id);
    prcsMngr->sendCmdToProcess(cmd);
}

void ProgramManager::sendAllStatus(){
    QMapIterator<QString, ProcessManager*> it(processesManager);
    while(it.hasNext()){
        it.next();
        sendProgramStatus(it.key(), it.value()->getStatus());
    }
}
